import secrets
from typing import Optional
from typing import Dict
from typing import Any

from pydantic import BaseSettings
from pydantic import validator
from pydantic import AnyUrl


class MysqlDsn(AnyUrl):
    allowed_schemes = {'mysql'}
    user_required = True


class RedisDsn(AnyUrl):
    allowed_schemes = {'redis'}

    @classmethod
    def validate_parts(cls, parts: Dict[str, str]) -> Dict[str, str]:
        defaults = {
            'domain': 'localhost' if not (parts['ipv4'] or parts['ipv6']) else '',
            'port': '6379'
        }
        for key, value in defaults.items():
            if not parts[key]:
                parts[key] = value
        return super().validate_parts(parts)


class RabbitMQDsn(AnyUrl):
    allowed_schemes = {'amqp'}


class Settings(BaseSettings):
    # JWT
    SECRET_KEY: str = secrets.token_urlsafe(32)
    ALGORITHM: str = 'HS256'
    ACCESS_TOKEN_EXPIRE_MINUTES: int = 60 * 24 * 3

    # 数据库
    MYSQL_ADDRESS: str
    MYSQL_USER: str
    MYSQL_PASSWORD: str
    MYSQL_DB: str
    MYSQL_DATABASE_URL: Optional[MysqlDsn] = None

    @validator("MYSQL_DATABASE_URL", pre=True)
    def assemble_db_connection(cls, v: Optional[str], values: Dict[str, Any]) -> Any:
        if isinstance(v, str):
            return v
        return MysqlDsn.build(
            scheme="mysql",
            user=values.get("MYSQL_USER"),
            password=values.get("MYSQL_PASSWORD"),
            host=values.get("MYSQL_ADDRESS"),
            path=f"/{values.get('MYSQL_DB') or ''}",
        )

    # redis, ip + 端口
    REDIS_ADDRESS: str
    REDIS_URL: Optional[RedisDsn] = None

    @validator("REDIS_URL", pre=True)
    def assemble_redis_connection(cls, v: Optional[str], values: Dict[str, Any]) -> Any:
        if isinstance(v, str):
            return v
        return RedisDsn.build(
            scheme="redis",
            host=values.get("REDIS_ADDRESS")
        )

    # rabbitMQ
    RABBITMQ_ADDRESS: str
    RABBITMQ_USER: str
    RABBITMQ_PASSWORD: str
    RABBITMQ_VHOST: str

    RABBITMQ_URL: Optional[RabbitMQDsn] = None

    @validator("RABBITMQ_URL", pre=True)
    def assemble_rabbitmq_connection(cls, v: Optional[str], values: Dict[str, Any]) -> Any:
        if isinstance(v, str):
            return v
        return RabbitMQDsn.build(
            scheme="amqp",
            host=values.get("RABBITMQ_ADDRESS"),
            user=values.get("RABBITMQ_USER"),
            password=values.get("RABBITMQ_PASSWORD"),
            path=f'/{values.get("RABBITMQ_VHOST")}'
        )

    # 短信服务(容联云) https://doc.yuntongxun.com/pe/5f029ae7a80948a1006e776e
    ACCOUNT_SID: str
    ACCOUNT_TOKEN: str
    APPID: str

    # Gitee 三方登录
    GITEE_ID: str = '6001020d3a7e2a1bac4cce89969f223a226a7cc33a8b62e47cc8838d1d8e4376'
    GITEE_URL: str = 'http://localhost:8000/gitee_back'
    GITEE_SECRET: str

    GITEE_REDIRECT: Optional[str] = None

    @validator("GITEE_REDIRECT", pre=True)
    def assemble_gitee_redict_url(cls, v: Optional[str], values: Dict[str, Any]) -> Any:
        """返回完整的 Gitee Oauth 重定向地址"""
        if isinstance(v, str):
            return v
        return f'https://gitee.com/oauth/authorize?client_id={values.get("GITEE_ID")}&redirect_uri=' \
               f'{values.get("GITEE_URL")}&response_type=code'

    # 邮件服务
    EMAIL_USER: str
    EMAIL_SECRET: str
    EMAIL_SMTP_HOST: str = 'smtp.163.com'

    # 支付宝信息

    # 存储服务信息

# pip freeze > requirements.txt
# settings = Settings(_env_file='../.env.development', _env_file_encoding='utf-8')
settings = Settings(_env_file='.env.development', _env_file_encoding='utf-8')
